/*
 * Copyright Hundsun Technologies Inc. All Rights Reserved.
 */

package stack

import (
	"errors"
	"sync"
)

// ErrStackFull 栈满
var ErrStackFull = errors.New("stack is full")

// ErrStackEmpty 栈空
var ErrStackEmpty = errors.New("stack is empty")

var emptyStackTop = -1

// Stack 一个goroutine安全的stack
type Stack struct {
	top  int
	cap  int
	data []interface{}
	sync.RWMutex
}

// New 创建一个指定容量的stack
func New(cap int) *Stack {
	return &Stack{top: -1, cap: cap, data: make([]interface{}, cap)}
}

// Size 返回栈中元素的个数
func (s *Stack) Size() int {
	s.RLock()
	defer s.RUnlock()
	if s.top == emptyStackTop {
		return 0
	}
	return s.top
}

// Peek 查看栈顶元素
func (s *Stack) Peek() (interface{}, error) {
	s.RLock()
	defer s.RUnlock()
	if s.top == emptyStackTop {
		return nil, ErrStackEmpty
	}
	return s.data[s.top], nil
}

// Pop 移除栈顶元素
func (s *Stack) Pop() (interface{}, error) {
	s.Lock()
	defer s.Unlock()
	if s.top == emptyStackTop {
		return nil, ErrStackEmpty
	}
	e := s.data[s.top]
	s.top--
	return e, nil
}

// Push 往栈顶放入一个元素
func (s *Stack) Push(e interface{}) error {
	s.Lock()
	defer s.Unlock()
	if s.top >= s.cap-1 {
		return ErrStackFull
	}
	s.top++
	s.data[s.top] = e
	return nil
}

// Clear 清空栈
func (s *Stack) Clear() {
	s.top = emptyStackTop
}
